import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JTextField;

import Entities.Diet;
import FileIO.readXML;
import FileIO.writeXML;

import Shapes.Ball;
import Shapes.Box2D;
import Shapes.Edge;
import Shapes.Flow;
import Shapes.Timeline;
import Shapes.parallelCoordinates;
import Shapes.pieBall;

import processing.core.*;
import processing.video.MovieMaker;
import testing.XMLReader; 

public class LCA_Checkbox extends PApplet {

	// which process has been selected
	int partX = 0;
	int partY = 0;
	boolean isQueried = false;
	boolean isQueryFixed = false;
	Box2D queryBox = null;

	PFont fontA;

	boolean isAdd = false;
	int sectionX = 0;
	int sectionY = 0;

	// the object
	Diet diet = null;
	readXML readfile = null;
	writeXML writefile = null;
	XMLReader filereader = null;

	// for the interface choices
	int num_process = 6; // now we set it as 6

	Element[] button_process = new Element[num_process]; // the process button
	PImage[] processsprite = new PImage[num_process]; // the pic for the
														// process_sprite
	float radium = 250;

	int num_impact = 2; // now we set it as 6
	Element[] button_impact = new Element[num_impact]; // the process button
	PImage[] impactsprite = new PImage[num_impact]; // the pic for the
													// process_sprite
	int selected_impact = 0;

	// the open page --- just for test;
	pieBall central_impact = null;
	ArrayList<pieBall> yearConsuming = new ArrayList<pieBall>();
	Timeline time = null;

	// for combine dateset
	boolean begincombine = false;
	int c_startx = 0;
	int c_starty = 0;
	int c_endx = 0;
	int c_endy = 0;
	Diet combinedDiet = new Diet();
	
	
	MovieMaker mm;

	public void setup() {
		size(1200, 800);
		
		 // Save uncompressed, at 15 frames per second
//		mm = new MovieMaker(this, width, height, "../resource/drawing.mov");
		  
		noStroke();
		smooth();

		// setup Font
		// Load the font. Fonts must be placed within the data
		// directory of your sketch. Use Tools > Create Font
		// to create a distributable bitmap font.
		// For vector fonts, use the createFont() function.
		fontA = loadFont("../resource/Ziggurat-32.vlw");

		// Set the font and its size (in units of pixels)
		textFont(fontA, 20);

		// ----------------------------here we give six kind of
		// processing------------------------------//

		int width_process_interval = this.width / (num_process + 1);

		for (int i = 0; i < num_process; i++) {
			String name = "";
			switch (i) {
			case 0:
				name = "farming";
				break;
			case 1:
				name = "manufacturing";
				break;
			case 2:
				name = "transportation";
				break;
			case 3:
				name = "retail";
				break;
			case 4:
				name = "storage";
				break;
			case 5:
				name = "cooking";
				break;
			}

			button_process[i] = new Element(width_process_interval * (i + 1),
					30, 50, 0.9f, 10.0f, 0.1f, button_process, i, name, 1);

		}

		int height_impact_interval = this.height / (num_impact + 1);

		for (int i = 0; i < num_impact; i++) {
			String name = "";
			switch (i) {
			case 0:
				name = "energy consuming";
				break;
			case 1:
				name = "land requirement";
				break;
			}
			button_impact[i] = new Element(20,
					height_impact_interval * (i + 1), 50, 0.9f, 10.0f, 0.1f,
					button_impact, i, name, 2);
		}

		// ----------------------------------------------------------//
		// ----------------------------here we give six kind of
		// pictures------------------------------//
		processsprite[0] = loadImage("../resource/farming.gif");
		processsprite[1] = loadImage("../resource/manufacturing.gif");
		processsprite[2] = loadImage("../resource/transportation.gif");
		processsprite[3] = loadImage("../resource/retail.gif");
		processsprite[4] = loadImage("../resource/storage.gif");
		processsprite[5] = loadImage("../resource/cooking.gif");

		impactsprite[0] = loadImage("../resource/storage.gif");
		impactsprite[1] = loadImage("../resource/cooking.gif");

		// prepare the impact in the middle
		for (int i = 0; i < 13; i++) {
			pieBall yearball = new pieBall(this);
			yearball.setup("../resource/con" + (1997 + i) + ".txt",
					this.width / 2, this.height / 2);
			this.yearConsuming.add(yearball);
		}

		// prepare the querybox
		queryBox = new Box2D(this);
		queryBox.setup(0, 0, 0);
		time = new Timeline(this);
		try {
			time.setupDates();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (diet != null) {
			diet.setupGraph(this);
			diet.genertateWholeView();
		}

	}

	public void draw() {
		background(255);

		// fill(0, 50);
		// rect(0, 0, width, height);

		if (this.begincombine) {
			line(c_startx, this.c_starty, this.c_endx, this.c_endy);
			ellipse(this.c_endx, this.c_endy, 10, 10);
		}

		// draw central impact;
		if (diet == null) {
			yearConsuming.get(time.datenow - 1997).draw();
			// central_impact.draw();
			time.draw();
		}

		// draw labels
		if (diet != null) {
			drawDiet();
			// /////////---------------------//

			// draw process
			for (int i = 0; i < num_process; i++) {
				button_process[i].update();
				button_process[i].display();
			}

			// draw impact
			for (int i = 0; i < num_impact; i++) {
				// button_impact[i].update();
				// button_impact[i].display();
			}
			// draw selecting windows

			if (isQueried) {

				stroke(153);
				if (!isQueryFixed) {
					queryBox.update(mouseX, mouseY, 20);
					queryBox.draw();
					partX = mouseX;
					partY = mouseY;
				} else {
					queryBox.update(partX, partY, 20);
					queryBox.draw();
				}
			}
			// -------------------------------//
		}
		// Add window's pixels to movie
	//	  mm.addFrame();
	}

	private void drawDiet() {
		// TODO Auto-generated method stub
		if (diet.getSceneGraph() != null) {
			for (int i = 0; i < diet.getSceneGraph().size(); i++) {

				diet.getBackBox().get(i).drawTransparent();

				diet.getSceneGraph().get(i).impactballs.get(0).draw();

				for (int j = 0; j < diet.getSceneGraph().get(i).num; j++) {
					// the center ball
					diet.getSceneGraph().get(i).balls.get(j).draw();

					// the nodes, the information
					if (diet.getSceneGraph().get(i).balls.get(j).isShowCheckbox) {
						diet.getSceneGraph().get(i).nodes.get(j).draw();
					}

					// the flow between nodes
					if (j != 0) {
						diet.getSceneGraph().get(i).flows.get(j - 1).draw();
					}
				}
			}
		}

	}

	public void keyPressed() {

		if (key == 'q') {
			isQueried = !isQueried;
		}

		if (key == 'f') {
			isQueryFixed = !isQueryFixed;
		}

		if (key == 'r') {
			
			try {

				readfile = new readXML(
						"/Users/chen/Documents/workspace/TestProcessing/src/resource/onefood.xml");
				diet = new Diet();

				diet.setFoods(readfile.parse());

				if (diet != null) {
					diet.setupGraph(this);
					diet.genertateWholeView();
				}

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		if (key == 'w') {

			try {
				if (diet != null) {

					writefile = new writeXML();
					writefile
							.write(diet,
									"/Users/chen/Documents/workspace/TestProcessing/src/resource/newFood.xml");
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (key == 'c') {
			if (diet != null) {
				this.begincombine = !this.begincombine;

				this.c_startx = this.c_starty = this.c_endx = this.c_endy = 0;
			}
		}
		
		 if (key == ' ') {
			    // Finish the movie if space bar is pressed
	//		    mm.finish();
			    // Quit running the sketch once the file is written
	//		    exit();
			  }

	}

	public void mouseClicked() {

	}

	public void mouseDragged() {

		time.mouseDragged();

		// draw combine line
		if (this.begincombine) {
			this.c_endx = this.mouseX;
			this.c_endy = this.mouseY;
			// line(c_startx,this.c_starty,this.c_endx,this.c_endy);
			// ellipse(this.c_endx,this.c_endy, 10, 10);

			// for combination
			if (diet != null) {
				for (int i = 0; i < diet.getBackBox().size(); i++) {
					if (diet.getBackBox().get(i)
							.iscombine(this.c_endx, this.c_endy, 2) != 2) {
						diet.getBackBox().get(i)
								.iscombine(this.c_startx, this.c_starty, 1);
					}

				}
			}
		}

	}

	public void mousePressed() {

		// this is for combine the dataset
		if (this.begincombine) {
			this.c_startx = this.mouseX;
			this.c_starty = this.mouseY;

			this.c_endx = this.mouseX;
			this.c_endy = this.mouseY;

			for (int i = 0; i < diet.getBackBox().size(); i++) {
				int selectedout = diet.getBackBox().get(i)
						.iscombine(this.c_startx, this.c_starty, 1);
				if (selectedout == 1) {
					diet.getBackBox().get(i).setIsStroke(true);
				}
			}

		}

		time.mousePressed();

		if (diet != null) {
			if (diet.getSceneGraph() != null) {
				for (int i = 0; i < diet.getSceneGraph().size(); i++) {

					for (int k = 0; k < diet.getSceneGraph().get(i)
							.getImpactBalls().size(); k++) {
						diet.getSceneGraph().get(i).getImpactBalls().get(k)
								.Pressed();
					}

					for (int j = 0; j < diet.getSceneGraph().get(i).num; j++) {

						diet.getSceneGraph().get(i).balls.get(j).pressed();
						// diet.getSceneGraph().get(i).nodes.get(j).pressed();
						// diet.getSceneGraph().get(i).flows.get(j).pressed();
					}
				}
			}
		}

		for (int i = 0; i < num_process; i++) {
			button_process[i].pressed();
		}

		for (int i = 0; i < num_impact; i++) {
			button_impact[i].pressed();
		}

	}

	public void mouseMoved() {

		// for mouse passby
		// if(diet!= null){
		// for(int i = 0; i<diet.getBackBox().size();i++)
		// {
		// diet.getBackBox().get(i).mousePassby();
		// }
		// }
		//
		for (int i = 0; i < num_process; i++) {
			button_process[i].mousePassby();
		}

		for (int i = 0; i < num_impact; i++) {
			button_impact[i].mousePassby();
		}

		if (diet != null) {
			if (diet.getSceneGraph() != null) {
				for (int i = 0; i < diet.getSceneGraph().size(); i++) {
					for (int j = 0; j < diet.getSceneGraph().get(i).num; j++) {
						if (this.isQueried) {
							diet.getSceneGraph().get(i).balls.get(j)
									.mousePassby();
						}
						// diet.getSceneGraph().get(i).nodes.get(j).mousePassby();
						// diet.getSceneGraph().get(i).flows.get(j).mousePassby();
					}
				}
			}
		}

	}

	public void mouseReleased() {

		// this is for combine the dataset
		if (this.begincombine) {
			this.c_endx = this.mouseX;
			this.c_endy = this.mouseY;

			this.begincombine = false;

			if (diet != null) {

				for (int i = 0; i < diet.getSceneGraph().size(); i++) {

					for (int k = 0; k < diet.getSceneGraph().get(i)
							.getImpactBalls().size(); k++) {
						
						diet.getSceneGraph().get(i).getImpactBalls().get(k)
								.Released();
					}
				}
				
				for (int i = 0; i < diet.getBackBox().size(); i++) {
					diet.getBackBox().get(i).setIsStroke(false);
				}
			}

		}

		// this is for the indicators, we choose
		int ispressed = -1;
		int selectType = 1;
		for (int i = 0; i < num_process; i++) {
			button_process[i].released();
			if (button_process[i].isPressed() == true) {
				ispressed = i;
			}
		}

		if (ispressed == -1) {
			selectType = 2;
			for (int i = 0; i < num_impact; i++) {
				button_impact[i].released();
				if (button_impact[i].isPressed() == true) {
					ispressed = i;
				}
			}

			if (ispressed == -1) {
				selectType = -1;
			}
		}

		if (selectType == 1) {
			// add one into the circle
			PVector d1 = new PVector(this.mouseX, this.mouseY);

			if (ispressed >= 0) {
				this.isAdd = true;
				// get the location for this member
				if (diet != null) {
					diet.addOneProcess(button_process[ispressed].name,
							this.mouseX, this.mouseY);
				}
			}
			this.isAdd = false;

		} else if (selectType == 2) {

			// which impact is selected.

			this.selected_impact = ispressed;
		}

		// this is for the processes we created

		if (diet != null) {
			if (diet.getSceneGraph() != null) {
				for (int i = 0; i < diet.getSceneGraph().size(); i++) {
					for (int j = 0; j < diet.getSceneGraph().get(i).num; j++) {
						diet.getSceneGraph().get(i).balls.get(j).pressed();
						// diet.getSceneGraph().get(i).nodes.get(j).pressed();
						// diet.getSceneGraph().get(i).flows.get(j).pressed();
					}
				}
			}
		}

	}

	// ---------------------this is extra
	// graphics------------------------------------------------------//

	public class Element {
		// Screen values
		float xpos, ypos;
		float tempxpos, tempypos;
		int size = 20;
		boolean over = false;
		boolean move = false;

		// Spring simulation constants
		float mass; // Mass
		float k = 0.2f; // Spring constant
		float damp; // Damping
		float rest_posx; // Rest position X
		float rest_posy; // Rest position Y

		// Spring simulation variables
		// float pos = 20.0; // Position
		float velx = 0.0f; // X Velocity
		float vely = 0.0f; // Y Velocity
		float accel = 0; // Acceleration
		float force = 0; // Force

		Element[] friends;
		int me;
		String name = "";
		int type; // 1- process 2-impact

		// Constructor
		Element(float x, float y, int s, float d, float m, float k_in,
				Element[] others, int id, String name, int type) {
			xpos = tempxpos = x;
			ypos = tempypos = y;
			rest_posx = x;
			rest_posy = y;
			size = s;
			damp = d;
			mass = m;
			k = k_in;
			friends = others;
			me = id;
			this.name = name;
			this.type = type;

		}

		public void update() {
			if (move) {
				rest_posy = mouseY;
				rest_posx = mouseX;
			}

			force = -k * (tempypos - rest_posy); // f=-ky
			accel = force / mass; // Set the acceleration, f=ma == a=f/m
			vely = damp * (vely + accel); // Set the velocity
			tempypos = tempypos + vely; // Updated position

			force = -k * (tempxpos - rest_posx); // f=-ky
			accel = force / mass; // Set the acceleration, f=ma == a=f/m
			velx = damp * (velx + accel); // Set the velocity
			tempxpos = tempxpos + velx; // Updated position

			if ((over() || move) && !otherOver()) {
				over = true;
			} else {
				over = false;
			}
		}

		// Test to see if mouse is over this spring
		public boolean over() {
			float disX = tempxpos - mouseX;
			float disY = tempypos - mouseY;
			if (sqrt(sq(disX) + sq(disY)) < size / 2) {
				return true;
			} else {
				return false;
			}
		}

		// Make sure no other springs are active
		public boolean otherOver() {
			if (type == 1) {
				for (int i = 0; i < num_process; i++) {
					if (i != me) {
						if (friends[i].over == true) {
							return true;
						}
					}
				}
			} else if (type == 2) {
				for (int i = 0; i < num_impact; i++) {
					if (i != me) {
						if (friends[i].over == true) {
							return true;
						}
					}
				}
			}
			return false;
		}

		public void display() {
			if (over) {

				fill(0);
				textSize(30);
				text(name, 850, 300);

				fill(153);

			} else {
				fill(255);
			}
			// ellipse(tempxpos, tempypos, size, size);
			int picindex = -1;

			if (type == 1) {
				if (name.equalsIgnoreCase("farming")) {
					picindex = 0;
				} else if (name.equalsIgnoreCase("manufacturing")) {
					picindex = 1;
				} else if (name.equalsIgnoreCase("transportation")) {
					picindex = 2;
				} else if (name.equalsIgnoreCase("retail")) {
					picindex = 3;
				} else if (name.equalsIgnoreCase("storage")) {
					picindex = 4;
				} else if (name.equalsIgnoreCase("cooking")) {
					picindex = 5;
				}

				image(processsprite[picindex], tempxpos - 30, tempypos - 30,
						60, 60);
			} else if (type == 2) {
				if (name.equalsIgnoreCase("energy consuming")) {
					picindex = 0;
				} else if (name.equalsIgnoreCase("land requirement")) {
					picindex = 1;
				}

				image(impactsprite[picindex], tempxpos - 30, tempypos - 30, 60,
						60);
			}
		}

		public void pressed() {
			if (over) {
				move = true;
			} else {
				move = false;
			}
		}

		public void released() {
			move = false;
			rest_posx = xpos;
			rest_posy = ypos;

		}

		public boolean isPressed() {
			if (over) {
				return true;
			} else {
				return false;
			}
		}

		public void mousePassby() {
		}
	}

	// a little modification for interface

	public class PopFrame extends JDialog {
		JTextField txt = null;
		JButton btnOK = null;

		PopFrame() {
			txt = new JTextField();
			getContentPane().add(txt, BorderLayout.NORTH);
			btnOK = new JButton("OK ");
			getContentPane().add(btnOK, BorderLayout.SOUTH);

			btnOK.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					hide();
				}
			});
		}

		public String getValue() {
			return (txt.getText());
		}
	}
	
	static public void main(String args[]) {
	    PApplet.main(new String[] { "--bgcolor=#FFFFFF", "LCA_Checkbox" });
	  }

}
